#ifndef TUSB564_H
#define TUSB564_H

#include <i2c.h>
#include <usart.h>
#include <systick.h>
#include <stdio.h>

#define TUSB564_I2C_SLAVE_ADDR 0x44

#define MUX_REG_GENERAL                 0x0A
#define MUX_REG_GENERAL_EQ_OVERRIDE                  (1<<4)
#define MUX_REG_GENERAL_DP_EN_CTRL                   (1<<3)
#define MUX_REG_GENERAL_FLIPSEL                      (1<<2)
#define MUX_REG_GENERAL_CTLSEL                       (3<<0)

#define MUX_REG_DP_CONTROLA             0x10
#define MUX_REG_DP_CONTROLA_DP1EQ_SEL                (15<<4)
#define MUX_REG_DP_CONTROLA_DP3EQ_SEL                (15<<0)

#define MUX_REG_DP_CONTROLB             0x11
#define MUX_REG_DP_CONTROLB_DP0EQ_SEL                (15<<4)
#define MUX_REG_DP_CONTROLB_DP2EQ_SEL                (15<<0)

#define MUX_REG_DP_CONTROLC             0x12
#define MUX_REG_DP_CONTROLC_SET_POWER_STATE          (3<<5)
#define MUX_REG_DP_CONTROLC_LANE_COUNT_SET           (31<<0)

#define MUX_REG_DP_CONTROLD             0x13
#define MUX_REG_DP_CONTROLD_AUX_SNOOP_DISABLE        (1<<7)
#define MUX_REG_DP_CONTROLD_AUX_SBU_OVR              (3<<4)
#define MUX_REG_DP_CONTROLD_DP3_DISABLE              (1<<3)
#define MUX_REG_DP_CONTROLD_DP2_DISABLE              (1<<2)
#define MUX_REG_DP_CONTROLD_DP1_DISABLE              (1<<1)
#define MUX_REG_DP_CONTROLD_DP0_DISABLE              (1<<0)

#define MUX_REG_USB3_1_CONTROLA         0x20
#define MUX_REG_USB3_1_CONTROLA_EQ2_SEL              (15<<4)
#define MUX_REG_USB3_1_CONTROLA_EQ1_SEL              (15<<0)

#define MUX_REG_USB3_1_CONTROLB         0x21
#define MUX_REG_USB3_1_CONTROLB_SSEQ_SEL             (15<<0)

#define MUX_REG_USB3_1_CONTROLC         0x22
#define MUX_REG_USB3_1_CONTROLC_CM_ACTIVE            (1<<7)
#define MUX_REG_USB3_1_CONTROLC_LFPS_EQ              (1<<6)
#define MUX_REG_USB3_1_CONTROLC_U2U3_LFPS_DEBOUNCE   (1<<5)
#define MUX_REG_USB3_1_CONTROLC_DISABLE_U2U3_RXDET   (1<<4)
#define MUX_REG_USB3_1_CONTROLC_DFP_RXDET_INTERVAL   (3<<2)
#define MUX_REG_USB3_1_CONTROLC_USB3_COMPLIANCE_CTRL (3<<2)

#define PIN_LEVEL(EQ1, EQ0)                          (EQ1 << 2 | EQ0)

typedef enum{
    level_0,
    level_R,
    level_F,
    level_1,
}gpio_level;

typedef enum{
    ufp_dB_F_0_9 = PIN_LEVEL(level_0, level_0),         // -0.9
    ufp_dB_0_2   = PIN_LEVEL(level_0, level_R),         // 0.2
    ufp_dB_1_2   = PIN_LEVEL(level_0, level_F),         // 1.2
    ufp_dB_2_2   = PIN_LEVEL(level_0, level_1),         // 2.2
    ufp_dB_3_1   = PIN_LEVEL(level_R, level_0),         // 3.1
    ufp_dB_4_0   = PIN_LEVEL(level_R, level_R),         // 4.0
    ufp_dB_4_8   = PIN_LEVEL(level_R, level_F),         // 4.8
    ufp_dB_5_6   = PIN_LEVEL(level_R, level_1),         // 5.6
    ufp_dB_6_3   = PIN_LEVEL(level_F, level_0),         // 6.3
    ufp_dB_7_0   = PIN_LEVEL(level_F, level_R),         // 7.0
    ufp_dB_7_5   = PIN_LEVEL(level_F, level_F),         // 7.5
    ufp_dB_8_1   = PIN_LEVEL(level_F, level_1),         // 8.1
    ufp_dB_8_5   = PIN_LEVEL(level_1, level_0),         // 8.5
    ufp_dB_9_1   = PIN_LEVEL(level_1, level_R),         // 9.1
    ufp_dB_9_5   = PIN_LEVEL(level_1, level_F),         // 9.5
    ufp_dB_9_9   = PIN_LEVEL(level_1, level_1),         // 9.9
}usb3_ufp_dB;

typedef enum{
    dfp_dB_F_2_4 = PIN_LEVEL(level_0, level_0),         // -2.4
    dfp_dB_F_1_3 = PIN_LEVEL(level_0, level_R),         // -1.3
    dfp_dB_F_0_4 = PIN_LEVEL(level_0, level_F),         // -0.4
    dfp_dB_0_7   = PIN_LEVEL(level_0, level_1),         // 0.7
    dfp_dB_1_5   = PIN_LEVEL(level_R, level_0),         // 1.5
    dfp_dB_2_5   = PIN_LEVEL(level_R, level_R),         // 2.5
    dfp_dB_3_2   = PIN_LEVEL(level_R, level_F),         // 3.2
    dfp_dB_4_0   = PIN_LEVEL(level_R, level_1),         // 4.0
    dfp_dB_4_8   = PIN_LEVEL(level_F, level_0),         // 4.8
    dfp_dB_5_5   = PIN_LEVEL(level_F, level_R),         // 5.5
    dfp_dB_6_0   = PIN_LEVEL(level_F, level_F),         // 6.0
    dfp_dB_6_6   = PIN_LEVEL(level_F, level_1),         // 6.6
    dfp_dB_7_1   = PIN_LEVEL(level_1, level_0),         // 7.1
    dfp_dB_7_6   = PIN_LEVEL(level_1, level_R),         // 7.6
    dfp_dB_8_0   = PIN_LEVEL(level_1, level_F),         // 8.0
    dfp_dB_8_5   = PIN_LEVEL(level_1, level_1),         // 8.5
}usb3_dfp_dB;

typedef enum{
    dp_dB_F_0_3 = PIN_LEVEL(level_0, level_0),          // -0.3
    dp_dB_1_6   = PIN_LEVEL(level_0, level_R),          // 1.6
    dp_dB_3_0   = PIN_LEVEL(level_0, level_F),          // 3.0
    dp_dB_4_4   = PIN_LEVEL(level_0, level_1),          // 4.4
    dp_dB_5_4   = PIN_LEVEL(level_R, level_0),          // 5.4
    dp_dB_6_5   = PIN_LEVEL(level_R, level_R),          // 6.5
    dp_dB_7_3   = PIN_LEVEL(level_R, level_F),          // 7.3
    dp_dB_8_1   = PIN_LEVEL(level_R, level_1),          // 8.1
    dp_dB_8_9   = PIN_LEVEL(level_F, level_0),          // 8.9
    dp_dB_9_5   = PIN_LEVEL(level_F, level_R),          // 9.5
    dp_dB_10_0  = PIN_LEVEL(level_F, level_F),          // 10.0
    dp_dB_10_6  = PIN_LEVEL(level_F, level_1),          // 10.6
    dp_dB_11_0  = PIN_LEVEL(level_1, level_0),          // 11.0
    dp_dB_11_4  = PIN_LEVEL(level_1, level_R),          // 11.4
    dp_dB_11_8  = PIN_LEVEL(level_1, level_F),          // 11.8
    dp_dB_12_1  = PIN_LEVEL(level_1, level_1),          // 12.1
}dp_lane_dB;

typedef enum{
    Disable_ALL,
    USB3_Only,
    DP_Only,
    DP_With_USB3,
}ctlsel;

typedef enum{
    Default,                  // AUX与SBU的连接由CTLSEL1和FLIPSEL决定
    Ovr1,                     // AUXn->SBU1   AUXp->SBU2
    Ovr2,                     // AUXn->SBU2   AUXp->SBU1
    Open,                     // 都不连接
}aux_sbu_ovr;

typedef enum{
    ms8,
    ms12
}dfp_rxdet_interval;

typedef enum{
    FSM,
    DFP_Direction,
    UFP_Direction,
    Disable,
}usb3_compliance_mode;

void tusb564_EQ(bool from_pin);
void tusb564_DP_EN(bool from_pin);
void tusb564_FLIP(bool flip);
void tusb564_CTLSEL(ctlsel ctl);
void tusb564_DP0EQ(dp_lane_dB db);
void tusb564_DP1EQ(dp_lane_dB db);
void tusb564_DP2EQ(dp_lane_dB db);
void tusb564_DP3EQ(dp_lane_dB db);
uint8_t tusb564_Power_State(void);
uint8_t tusb564_Line_Count(void);
void tusb564_AUX_SNOOP(bool enable);
void tusb564_AUX_SBU_OVR(aux_sbu_ovr ovr);
void tusb564_DP0(bool enable);
void tusb564_DP1(bool enable);
void tusb564_DP2(bool enable);
void tusb564_DP3(bool enable);
void tusb564_USB3_EQ1(usb3_ufp_dB db);
void tusb564_USB3_EQ2(usb3_ufp_dB db);
void tusb564_USB3_SSEQ(usb3_dfp_dB db);
bool tusb564_CM_Active(void);
void tusb564_LFPS_EQ(bool apply);
void tusb564_U2U3_LFPS_DEBOUNCE(bool debounce);
void tusb564_U2U3_RXDET(bool enable);
void tusb564_DFP_RXDET_INTERVAL(dfp_rxdet_interval rxdet);
void tusb564_USB3_COMPLIANCE(usb3_compliance_mode mode);

#endif

